package com.ssh.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by ZK on 2018/2/2.
 * 功能：当做工具类写sql
 */
public abstract class SqlHelper {

    /*************************************************************************************************************************
     *                                                  Start:  连接等相关申明                                               *
     ************************************************************************************************************************/
    private static Logger logger = LoggerFactory.getLogger(SqlHelper.class);
    public  abstract Connection getConnection() ;
    public boolean autoCloseConneciton=true;
    private static  ThreadLocal<Connection> connectionThreadLocal=new ThreadLocal<Connection>();
    //----------------------------------------------------End:  连接等相关申明-----------------------------------------------//


    /*************************************************************************************************************************
     *                                               Start:  getCountSql方法                                                 *
     *                                               参数：  String sql                                                      *
     *                                               功能：  返回执行参数Sql能够得到记录数量的sql语句                        *
     *                                                      如果要返回数量，要结合 getOnlyStringValue 方法                   *
     *                                        比如：dbHelper.getOnlyStringValue(dbHelper.getCountSql(sql),new Object[]{参数})*
     *                                               返回：  String                                                          *
     ************************************************************************************************************************/
    public String getCountSql(String sql) {
        String countSql = "select count(0) from (";
        countSql = countSql + " " + sql+" ) k";
        System.out.println("countSql=========>"+countSql);
        return countSql;
    }
    //--------------------------------------------------End:  getCountSql方法-----------------------------------------------------//





    /*************************************************************************************************************************
     *                                               Start:  getRows方法                                                     *
     *                                               参数：  String sql, Object[] params                                     *
     *                                               功能：  执行select语句，返回结果集                                         *
     *                                               返回：  List<Map>                                                       *
     ************************************************************************************************************************/
    public List<Map> getRows(String sql, Object[] params) {
        List<Map> list = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        Connection currentConn = connectionThreadLocal.get();
        if(currentConn ==null){
            currentConn = getConnection();
            connectionThreadLocal.set(currentConn);
        }
        try {
            st = currentConn.prepareStatement(sql);
            setParams(params, st);
            rs = st.executeQuery();
            if (rs != null) {
                ResultSetMetaData meta = rs.getMetaData();
                int colCount = rs.getMetaData().getColumnCount();
                list = new ArrayList<Map>();
                HashMap<String,Object> pro = null;
                while (rs.next()) {
                    pro = new HashMap<String,Object>();
                    for (int k = 1; k < colCount + 1; k++) {
                        String colName = meta.getColumnLabel(k);//getColumnName.(k);
                        Object objectValue = rs.getObject(colName);
                        if(objectValue!=null){
                            if(meta.getColumnType(k)== Types.CLOB){
                                pro.put(colName.toLowerCase(),rs.getString(colName));
                            }else{
                                pro.put(colName.toLowerCase(),objectValue.toString());
                            }
                        }else{
                            pro.put(colName.toLowerCase(),"");
                        }
                    }
                    list.add(pro);
                }
            }
        } catch (SQLException e) {
            logger.error("ERROR,sql="+sql,e);
        } finally {
            closeStatement( st, rs);
        }
        return list;
    }
    //--------------------------------------------------End:  getRows方法-----------------------------------------------------//







    /*************************************************************************************************************************
     *                                               Start:  getValue方法                                                    *
     *                                               参数：  String sql,String col, Object[] params                          *
     *                                               功能：  执行select语句根据参数的字段返回这条唯一记录的对应字段的值            *
     *                                               返回：  String                                                          *
     ************************************************************************************************************************/
    public String getValue(String sql ,String col,Object[] params) {
        List<Map> maps = this.getRows(sql,params);
        if(maps!=null&&maps.size()>0){
            if("".equals(col)||col==null){
                return "";
            }else{
                return maps.get(0).get(col.toLowerCase())+"";
            }
        }
        return "";
    }
    //--------------------------------------------------End:  getValue方法---------------------------------------------------//






    /*************************************************************************************************************************
     *                                               Start:  getOnlyStringValue方法                                          *
     *                                               参数：  String sql, Object[] params                                     *
     *                                               功能：  执行select语句（语句只有一个字段，返回一条记录），                   *
     *                                                       返回这条记录唯一的字段                                            *
     *                                               返回：  String                                                          *
     ************************************************************************************************************************/
    public  String getOnlyStringValue(String sql, Object[] params){
        String[] s = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try {
            Connection currentConn = connectionThreadLocal.get();
            if(currentConn ==null){
                currentConn = getConnection();
                connectionThreadLocal.set(currentConn);
            }
            st = currentConn.prepareStatement(sql);
            setParams(params, st);
            rs = st.executeQuery();
            if (rs != null) {
                int colCount = rs.getMetaData().getColumnCount();
                if (rs.next()) {
                    s = new String[colCount];
                    for (int k = 0; k < colCount; k++) {
                        s[k] = rs.getString(k + 1);
                    }
                }
            }
        } catch (SQLException e) {
            logger.error("ERROR,sql="+sql,e);
        } finally {
            closeStatement( st, rs);
        }
        if(s==null){
            return null;
        }
        return s[0];
    }
    //--------------------------------------------------End:  getOnlyStringValue方法--------------------------------------------//






    /*************************************************************************************************************************
     *                                               Start:  runSql方法                                                      *
     *                                               参数：  String sql, Object[] params                                     *
     *                                               功能：  执行insert  update  delete语句                                  *
     *                                               返回：  无                                                              *
     *                                               注意：  执行该方法时  需要try catch!                                    *
     ************************************************************************************************************************/
    public void runSql(String sql, Object[] params) throws SQLException {
        PreparedStatement st = null;
        try {
            Connection currentConn = connectionThreadLocal.get();
            if(currentConn ==null){
                currentConn = getConnection();
                connectionThreadLocal.set(currentConn);
            }
            st = currentConn.prepareStatement(sql);
            setParams(params, st);
            st.execute();
        }
        catch (SQLException ex) {
            logger.error("ERROR,sql="+sql,ex);
            throw ex;
        }finally{
            closeStatement(st,null);
        }
    }
    //--------------------------------------------------End:  runSql方法-------------------------------------------------//














    /*************************************************************************************************************************
     *                                               Start:  辅助方法                                                        *
     *                                               包括：  setParams /   closeStatement  /                                 *
     *                                                      isAutoCloseConneciton   /  closeConn                             *
     ************************************************************************************************************************/
    private void setParams(Object[] params, PreparedStatement st)
            throws SQLException {
        if (params != null) {
            int len=params.length;
            for (int pi = 0; pi < len; pi++) {
                if(params[pi] instanceof java.util.Date){
                    st.setTimestamp(pi+1,new Timestamp(((java.util.Date)params[pi]).getTime()));
                }else{
                    st.setObject(pi+1, params[pi]);
                }
            }
        }
    }
    public void closeStatement(Statement st, ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();
                rs = null;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if (st != null) {
                st.close();
                st = null;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        if(isAutoCloseConneciton()){
            closeConn();
        }
    }
    public boolean isAutoCloseConneciton() {
        return autoCloseConneciton;
    }
    public  void closeConn(){
        try {
            Connection currentConn = connectionThreadLocal.get();
            if (currentConn != null) {
                currentConn.close();
                connectionThreadLocal.remove();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //-------------------------------------------------End:  辅助方法--------------------------------------------------------//




}
